#include "StdAfx.h"
#include "Rubik.h"
#include "d3dUtility.h"

#include <vector>

using namespace rubik;
	
//right-red, left-orange, bottom-white, top-yellow, back-green, front-blue
FaceColor fc[CUBECOUNT] = {
	// front-bottom
	{FACE_DEFAULT,FACE_ORANGE,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x01100100},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x00100100},
	{FACE_RED,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x10100100},
	// middle-bottom
	{FACE_DEFAULT,FACE_ORANGE,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x01100000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x00100000},
	{FACE_RED,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x10100000},
	// back-bottom
	{FACE_DEFAULT,FACE_ORANGE,FACE_WHITE,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x01101000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x00101000},
	{FACE_RED,FACE_DEFAULT,FACE_WHITE,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x10101000},
	// front-middle
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x01000100},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x00000100},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_BLUE,0x10000100},
	// middle-middle
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x01000000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x00000000},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,0x10000000},
	// back-middle
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x01001000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x00001000},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_GREEN,FACE_DEFAULT,0x10001000},
	// front-top
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_BLUE,0x01010100},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_BLUE,0x00010100},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_BLUE,0x10010100},
	// middle-top
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_DEFAULT,0x01010000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_DEFAULT,0x00010000},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_DEFAULT,FACE_DEFAULT,0x10010000},
	// back-top
	{FACE_DEFAULT,FACE_ORANGE,FACE_DEFAULT,FACE_YELLOW,FACE_GREEN,FACE_DEFAULT,0x01011000},
	{FACE_DEFAULT,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_GREEN,FACE_DEFAULT,0x00011000},
	{FACE_RED,FACE_DEFAULT,FACE_DEFAULT,FACE_YELLOW,FACE_GREEN,FACE_DEFAULT,0x10011000}
};

D3DMATERIAL9 mtrl[6] = {d3d::RED_MTRL,d3d::YELLOW_MTRL,d3d::GREEN_MTRL,d3d::WHITE_MTRL,d3d::BLUE_MTRL,d3d::ORANGE_MTRL};

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

// Begin class CCube
CCube::CCube()
{
	m_pMesh = NULL;
}

CCube::~CCube()
{
	d3d::Release<ID3DXMesh*>(m_pMesh);
}

bool CCube::CreateCube(IDirect3DDevice9* device)
{
	HRESULT hr = 0;

	hr = D3DXCreateMeshFVF(TRIANGLECOUNT,24,D3DXMESH_MANAGED,Vertex::FVF,device,&m_pMesh);

	if(FAILED(hr))
	{
		::MessageBoxA(NULL,"rubik::CCube::D3DXCreateMeshFVF() - FAILED",NULL,MB_OK);
		return false;
	}

	//
	// Fill in vertices of a box
	//
	Vertex* v = 0;
	m_pMesh->LockVertexBuffer(0, (void**)&v);

	// fill in the front face vertex data
	v[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f);
	v[1] = Vertex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f);
	v[2] = Vertex( 1.0f,  1.0f, -1.0f, 0.0f, 0.0f, -1.0f);
	v[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f);

	// fill in the back face vertex data
	v[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[6] = Vertex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f);
	v[7] = Vertex(-1.0f,  1.0f, 1.0f, 0.0f, 0.0f, 1.0f);

	// fill in the top face vertex data
	v[8]  = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f);
	v[9]  = Vertex(-1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f);
	v[10] = Vertex( 1.0f, 1.0f,  1.0f, 0.0f, 1.0f, 0.0f);
	v[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f);

	// fill in the bottom face vertex data
	v[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f);
	v[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f);
	v[14] = Vertex( 1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f);
	v[15] = Vertex(-1.0f, -1.0f,  1.0f, 0.0f, -1.0f, 0.0f);
	 
	// fill in the left face vertex data
	v[16] = Vertex(-1.0f, -1.0f,  1.0f, -1.0f, 0.0f, 0.0f);
	v[17] = Vertex(-1.0f,  1.0f,  1.0f, -1.0f, 0.0f, 0.0f);
	v[18] = Vertex(-1.0f,  1.0f, -1.0f, -1.0f, 0.0f, 0.0f);
	v[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f);
	 
	// fill in the right face vertex data
	v[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f);
	v[21] = Vertex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f, 0.0f);
	v[22] = Vertex( 1.0f,  1.0f,  1.0f, 1.0f, 0.0f, 0.0f);
	v[23] = Vertex( 1.0f, -1.0f,  1.0f, 1.0f, 0.0f, 0.0f);

	m_pMesh->UnlockVertexBuffer();

	//
	// Define the triangles of the box
	//
	WORD* i = 0;
	m_pMesh->LockIndexBuffer(0, (void**)&i);

	// fill in the front face index data
	i[0] = 0; i[1] = 1; i[2] = 2;
	i[3] = 0; i[4] = 2; i[5] = 3;

	// fill in the back face index data
	i[6] = 4; i[7]  = 5; i[8]  = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	// fill in the top face index data
	i[12] = 8; i[13] =  9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	// fill in the bottom face index data
	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;
	 
	// fill in the left face index data
	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;
	 
	// fill in the right face index data
	i[30] = 20; i[31] = 21; i[32] = 22;
	i[33] = 20; i[34] = 22; i[35] = 23;

	m_pMesh->UnlockIndexBuffer();

	//
	// Optimize the mesh to generate an attribute table.
	//
	std::vector<DWORD> adjacencyBuffer(m_pMesh->GetNumFaces() * 3);
	m_pMesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);

	hr = m_pMesh->OptimizeInplace(		
		D3DXMESHOPT_ATTRSORT |
		D3DXMESHOPT_COMPACT  |
		D3DXMESHOPT_VERTEXCACHE,
		&adjacencyBuffer[0],
		0, 0, 0);

	if(FAILED(hr))
	{
		::MessageBoxA(NULL,"rubik::CCube::D3DXCreateMeshFVF() - Optimize adjacency FAILED",NULL,MB_OK);
		return false;
	}

	return true;
}

bool CCube::ColorFace(FaceColor* color)
{
	if(m_pMesh)
	{
		DWORD *attributeBuffer = 0;
		m_pMesh->LockAttributeBuffer(0,&attributeBuffer);

		for(int index = 0; index < TRIANGLECOUNT; index++)
		{
			attributeBuffer[index] = ((int*)color)[index/2];
		}
		m_iBelow = color->below;
	}
	return true;
}

void CCube::DrawCube(DWORD attribute)
{
	m_pMesh->DrawSubset(attribute);
}
// End class CCube

// Begin class CRubik
CRubik::CRubik(IDirect3DDevice9 **p)
{
	m_pDevice = *p;
	memset(m_pCube,0,sizeof(m_pCube));
	memset(m_iRotateCount,0x48,sizeof(m_iRotateCount));
	m_iLockFace = 0;
}

CRubik::~CRubik(void)
{
}

bool CRubik::Setup()
{
	// cubes
	for(int i = 0; i < CUBECOUNT; i++)
	{
		m_pCube[i] = new CCube;
		if(!m_pCube[i]->CreateCube(m_pDevice))
			return false;
		m_pCube[i]->ColorFace(&fc[i]);
	}

	// translation matrix
	// from bottom to top, from left to right, from front to back
	// front-bottom
	D3DXMatrixTranslation(&m_TransMatrix[0],-2.01f,-2.01f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[1],0.0f,-2.01f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[2],2.01f,-2.01f,-2.01f);
	// middle-bottom
	D3DXMatrixTranslation(&m_TransMatrix[3],-2.01f,-2.01f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[4],0.0f,-2.01f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[5],2.01f,-2.01f,0.0f);
	// back-bottom
	D3DXMatrixTranslation(&m_TransMatrix[6],-2.01f,-2.01f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[7],0.0f,-2.01f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[8],2.01f,-2.01f,2.01f);
	// front-middle
	D3DXMatrixTranslation(&m_TransMatrix[9],-2.01f,0.0f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[10],0.0f,0.0f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[11],2.01f,0.0f,-2.01f);
	// middle-middle
	D3DXMatrixTranslation(&m_TransMatrix[12],-2.01f,0.0f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[13],0.0f,0.0f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[14],2.01f,0.0f,0.0f);
	// back-middle
	D3DXMatrixTranslation(&m_TransMatrix[15],-2.01f,0.0f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[16],0.0f,0.0f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[17],2.01f,0.0f,2.01f);
	// front-top
	D3DXMatrixTranslation(&m_TransMatrix[18],-2.01f,2.01f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[19],0.0f,2.01f,-2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[20],2.01f,2.01f,-2.01f);
	// middle-top
	D3DXMatrixTranslation(&m_TransMatrix[21],-2.01f,2.01f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[22],0.0f,2.01f,0.0f);
	D3DXMatrixTranslation(&m_TransMatrix[23],2.01f,2.01f,0.0f);
	// back-top
	D3DXMatrixTranslation(&m_TransMatrix[24],-2.01f,2.01f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[25],0.0f,2.01f,2.01f);
	D3DXMatrixTranslation(&m_TransMatrix[26],2.01f,2.01f,2.01f);

	// light
	D3DXVECTOR3 dir(1.0f,-0.0f,0.25f);
	D3DXCOLOR c = d3d::WHITE;
	D3DLIGHT9 dirlight = d3d::InitDirectionalLight(&dir,&c);

	m_pDevice->SetLight(0,&dirlight);
	m_pDevice->LightEnable(0,true);
	m_pDevice->SetRenderState(D3DRS_NORMALIZENORMALS,true);
	m_pDevice->SetRenderState(D3DRS_LIGHTING,true);

	// camera
	D3DXVECTOR3 pos(0.0f, 0.0f, -10.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMATRIX V;
	D3DXMatrixLookAtLH(
		&V,
		&pos,
		&target,
		&up);


	m_pDevice->SetTransform(D3DTS_VIEW, &V);
	// projection matrix
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f, // 90 - degree
		(float)width / (float)height,
		1.0f,
		1000.0f);
	m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

bool CRubik::Display( float timeDelta )
{
	if( m_pDevice )
	{
		//
		// Update: Rotate the cube.
		//
		static float x = 0.0f;

		if(::GetAsyncKeyState(VK_UP) & 0x8000f)
			x += timeDelta;
		else if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
			x -= timeDelta;

		if( x >= 6.28f )
			x = 0.0f;

		static float y = 0.0f;

		if(::GetAsyncKeyState(VK_LEFT) & 0x8000f)
			y += timeDelta;
		else if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
			y -= timeDelta;

		if( y >= 6.28f )
			y = 0.0f;

		LockFace();
		//
		// Render
		//
		m_pDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
		m_pDevice->BeginScene();

		for(int j = 0; j < CUBECOUNT; j++)
		{
			D3DXMATRIX rotate;
			RotateFace(&rotate,timeDelta,m_pCube[j],x,y);
			D3DXMATRIX World;
			World = m_TransMatrix[j] * rotate;

			m_pDevice->SetTransform(D3DTS_WORLD, &World);

			for(int i = 0; i < 6; i++)
			{
				m_pDevice->SetMaterial(&mtrl[i]);
				m_pCube[j]->DrawCube(i);
			}
		}

		m_pDevice->EndScene();
		m_pDevice->Present(0, 0, 0, 0);
	}

	return true;
}

void CRubik::Cleanup()
{
	for(int i = 0; i < CUBECOUNT; i++)
	{
		delete m_pCube[i];
		m_pCube[i] = NULL;
	}
	d3d::Release<IDirect3DDevice9*>(m_pDevice);
}

void CRubik::LockFace()
{
	if(::GetAsyncKeyState('Q') & 0x8000f)
		m_iLockFace = LOCK_NULL;
	else if(::GetAsyncKeyState('1') & 0x8000f)
		m_iLockFace = LOCK_RIGHT;
	else if(::GetAsyncKeyState('2') & 0x8000f)
		m_iLockFace = LOCK_LEFT;
	else if(::GetAsyncKeyState('3') & 0x8000f)
		m_iLockFace = LOCK_DOWN;
	else if(::GetAsyncKeyState('4') & 0x8000f)
		m_iLockFace = LOCK_TOP;
	else if(::GetAsyncKeyState('5') & 0x8000f)
		m_iLockFace = LOCK_BACK;
	else if(::GetAsyncKeyState('6') & 0x8000f)
		m_iLockFace = LOCK_FRONT;
}

void CRubik::RotateFace(D3DXMATRIX *pRotate, float time, CCube* pCube, float xAngle, float yAngle)
{
	if(pRotate == NULL)
		return;

	static bool keydown = true;
	static float dt = 0;
	static int flag = 0;
	static int clock = 0;

	dt += time;
	if(dt > 20.0f)
	{
		dt = 0;
		keydown = true;
	}

	if(keydown && (::GetAsyncKeyState('0') & 0x8000f))//clockwise
	{
		clock = 1;
		keydown = false;
		flag += 1;
	}
	else if(keydown && (::GetAsyncKeyState('9') & 0x8000f))//anticlockwise
	{
		clock = -1;
		keydown = false;
		flag -= 1;
	}

	float zAngle = 0.0f;
	switch(m_iLockFace)
	{
	case LOCK_NULL:
		break;
	case LOCK_RIGHT:
		if(pCube->m_iBelow & 0x10000000)
		{
			xAngle += flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x00100000)//bottom->front
			{
				pCube->m_iBelow &= (~0x00100000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00000100;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00001000;
			}
			else if(pCube->m_iBelow & 0x00010000)//top->back
			{
				pCube->m_iBelow &= (~0x00010000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00001000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00000100;
			}
			if(pCube->m_iBelow & 0x00001000)//back->bottom
			{
				pCube->m_iBelow &= (~0x00001000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00100000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00010000;
			}
			else if(pCube->m_iBelow & 0x00000100)//front->top
			{
				pCube->m_iBelow &= (~0x00000100);
				if(clock == 1)
					pCube->m_iBelow |= 0x00010000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00100000;
			}
		}
		break;
	case LOCK_LEFT:
		if(pCube->m_iBelow & 0x01000000)
		{
			xAngle -= flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x00100000)//bottom->back
			{
				pCube->m_iBelow &= (~0x00100000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00001000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00000100;
			}
			else if(pCube->m_iBelow & 0x00010000)//top->front
			{
				pCube->m_iBelow &= (~0x00010000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00000100;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00001000;
			}
			if(pCube->m_iBelow & 0x00001000)//back->top
			{
				pCube->m_iBelow &= (~0x00001000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00010000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00100000;
			}
			else if(pCube->m_iBelow & 0x00000100)//front->bottom
			{
				pCube->m_iBelow &= (~0x00000100);
				if(clock == 1)
					pCube->m_iBelow |= 0x00100000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00010000;
			}
		}
		break;
	case LOCK_DOWN:
		if(pCube->m_iBelow & 0x00100000)
		{
			yAngle -= flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x10000000)//right->back
			{
				pCube->m_iBelow &= (~0x10000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00001000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00000100;
			}
			else if(pCube->m_iBelow & 0x01000000)//left->front
			{
				pCube->m_iBelow &= (~0x01000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00000100;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00001000;
			}
			if(pCube->m_iBelow & 0x00001000)//back->left
			{
				pCube->m_iBelow &= (~0x00001000);
				if(clock == 1)
					pCube->m_iBelow |= 0x01000000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x10000000;
			}
			else if(pCube->m_iBelow & 0x00000100)//front->right
			{
				pCube->m_iBelow &= (~0x00000100);
				if(clock == 1)
					pCube->m_iBelow |= 0x10000000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x01000000;
			}
		}
		break;
	case LOCK_TOP:
		if(pCube->m_iBelow & 0x00010000)
		{
			yAngle += flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x10000000)//right->front
			{
				pCube->m_iBelow &= (~0x10000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00000100;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00001000;
			}
			else if(pCube->m_iBelow & 0x01000000)//left->back
			{
				pCube->m_iBelow &= (~0x01000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00001000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00000100;
			}
			if(pCube->m_iBelow & 0x00001000)//back->right
			{
				pCube->m_iBelow &= (~0x00001000);
				if(clock == 1)
					pCube->m_iBelow |= 0x10000000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x01000000;
			}
			else if(pCube->m_iBelow & 0x00000100)//front->left
			{
				pCube->m_iBelow &= (~0x00000100);
				if(clock == -1)
					pCube->m_iBelow |= 0x10000000;
				else if(clock == 1)
					pCube->m_iBelow |= 0x01000000;
			}
		}
		break;
	case LOCK_BACK:
		if(pCube->m_iBelow & 0x00001000)
		{
			zAngle = flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x10000000)//right->top
			{
				pCube->m_iBelow &= (~0x10000000);
				if(clock == -1)
					pCube->m_iBelow |= 0x00100000;
				else if(clock == 1)
					pCube->m_iBelow |= 0x00010000;
			}
			else if(pCube->m_iBelow & 0x01000000)//left->bottom
			{
				pCube->m_iBelow &= (~0x01000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00010000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00100000;
			}
			if(pCube->m_iBelow & 0x00100000)//bottom->right
			{
				pCube->m_iBelow &= (~0x00100000);
				if(clock == -1)
					pCube->m_iBelow |= 0x01000000;
				else if(clock == 1)
					pCube->m_iBelow |= 0x10000000;
			}
			else if(pCube->m_iBelow & 0x00010000)//top->left
			{
				pCube->m_iBelow &= (~0x00010000);
				if(clock == -1)
					pCube->m_iBelow |= 0x10000000;
				else if(clock == 1)
					pCube->m_iBelow |= 0x01000000;
			}
		}
		break;
	case LOCK_FRONT:
		if(pCube->m_iBelow & 0x00000100)
		{
			zAngle = -flag*D3DX_PI/2.0f;

			if(pCube->m_iBelow & 0x10000000)//right->bottom
			{
				pCube->m_iBelow &= (~0x10000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00100000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00010000;
			}
			else if(pCube->m_iBelow & 0x01000000)//left->top
			{
				pCube->m_iBelow &= (~0x01000000);
				if(clock == 1)
					pCube->m_iBelow |= 0x00010000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x00100000;
			}
			if(pCube->m_iBelow & 0x00100000)//bottom->left
			{
				pCube->m_iBelow &= (~0x00100000);
				if(clock == 1)
					pCube->m_iBelow |= 0x01000000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x10000000;
			}
			else if(pCube->m_iBelow & 0x00010000)//top->right
			{
				pCube->m_iBelow &= (~0x00010000);
				if(clock == 1)
					pCube->m_iBelow |= 0x10000000;
				else if(clock == -1)
					pCube->m_iBelow |= 0x01000000;
			}
		}
		break;
	default:
		break;
	}

	D3DXMATRIX xRot;
	D3DXMatrixRotationX(&xRot,xAngle);
	D3DXMATRIX yRot;
	D3DXMatrixRotationY(&yRot, yAngle);
	D3DXMATRIX zRot;
	D3DXMatrixRotationZ(&zRot, zAngle);

	*pRotate = xRot * yRot * zRot;

}
// End class CRubik